// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.editors.dnd;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.dengues.core.DenguesCorePlugin;
import org.dengues.core.components.EGlobalComponentNames;
import org.dengues.core.components.ENodeParameterName;
import org.dengues.core.components.IXMLComponent;
import org.dengues.core.metadata.MetadataHelper;
import org.dengues.core.metadata.MetadataTable;
import org.dengues.core.prefs.IDenguesPrefsConstant;
import org.dengues.core.warehouse.ENavNodeType;
import org.dengues.core.warehouse.ENodeCategoryName;
import org.dengues.core.warehouse.IWarehouseNode;
import org.dengues.core.warehouse.IWarehouseObject;
import org.dengues.core.warehouse.WarehouseLabelUtil;
import org.dengues.designer.ui.database.commands.DBTableCreateCommand;
import org.dengues.designer.ui.database.editors.GEFDatabaseEditor;
import org.dengues.designer.ui.process.editors.GEFComponentsEditor;
import org.dengues.designer.ui.process.models.CompBlock;
import org.dengues.designer.ui.process.models.CompNode;
import org.dengues.designer.ui.process.models.CompProcess;
import org.dengues.model.database.DBTable;
import org.dengues.model.database.DatabaseDiagram;
import org.dengues.model.database.DiagramChild;
import org.dengues.model.warehouse.ProcessType;
import org.dengues.ui.DenguesUiPlugin;
import org.dengues.ui.editors.AbstractGenericGEFEditor;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.util.TransferDropTargetListener;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.graphics.Point;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf 2007-12-13 qiang.zhang $
 * 
 */
public class GEFEditorDropTargetListener implements TransferDropTargetListener {

    private IWarehouseNode node;

    private CompProcess process;

    private GEFComponentsEditor editor;

    private DatabaseDiagram database;

    private GEFDatabaseEditor databaseEditor;

    private List<DBTable> tables;

    /**
     * Qiang.Zhang.Adolf@gmail.com GEFEditorDropTargetListener constructor comment.
     * 
     * @param editor
     */
    public GEFEditorDropTargetListener(AbstractGenericGEFEditor editor) {
        if (editor instanceof GEFComponentsEditor) {
            this.editor = (GEFComponentsEditor) editor;
            process = this.editor.getProcess();
        } else if (editor instanceof GEFComponentsEditor) {
            this.databaseEditor = (GEFDatabaseEditor) editor;
            this.database = this.databaseEditor.getDatabaseDiagram();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.util.TransferDropTargetListener#getTransfer()
     */
    public Transfer getTransfer() {
        return LocalSelectionTransfer.getTransfer();
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.util.TransferDropTargetListener#isEnabled(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public boolean isEnabled(DropTargetEvent event) {
        boolean isEnabled = false;
        if (process != null) {
            DropTarget source = (DropTarget) event.getSource();
            Transfer[] transfers = source.getTransfer();
            for (Transfer transfer : transfers) {
                if (transfer == getTransfer()) {
                    LocalSelectionTransfer transfer2 = (LocalSelectionTransfer) transfer;
                    StructuredSelection selection = (StructuredSelection) transfer2.getSelection();
                    if (!selection.isEmpty()) {
                        node = (IWarehouseNode) selection.getFirstElement();
                        isEnabled = node != null
                                && node.getNodeType().compareTo(ENavNodeType.ELEMENT) == 0
                                && (EGlobalComponentNames.getName(node.getCategoryName(), event.detail) != null || ENodeCategoryName.BLOCKS
                                        .equals(node.getCategoryName())) && !node.isBin();
                    }
                }
            }
        } else if (database != null) {
            DropTarget source = (DropTarget) event.getSource();
            Transfer[] transfers = source.getTransfer();
            for (Transfer transfer : transfers) {
                if (transfer == getTransfer()) {
                    LocalSelectionTransfer transfer2 = (LocalSelectionTransfer) transfer;
                    StructuredSelection selection = (StructuredSelection) transfer2.getSelection();
                    if (!selection.isEmpty()) {
                        tables = new ArrayList<DBTable>();
                        for (Object object3 : selection.toList()) {
                            if (object3 instanceof IWarehouseNode) {
                                node = (IWarehouseNode) object3;
                                isEnabled = node != null
                                        && (node.getCategoryName().compareTo(ENodeCategoryName.TABLE) == 0 || node
                                                .getCategoryName().compareTo(ENodeCategoryName.DATABASE) == 0) && !node.isBin();
                                if (isEnabled) {
                                    IWarehouseObject object = node.getObject();
                                    if (object != null) {
                                        Object data = object.getData();
                                        if (data instanceof DBTable) {
                                            addDBTable(data);
                                        } else if (data instanceof DatabaseDiagram) {
                                            for (Object child : ((DatabaseDiagram) data).getDbChildren()) {
                                                if (child instanceof DBTable) {
                                                    addDBTable(child);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            isEnabled = tables != null && !tables.isEmpty();
        }
        return isEnabled;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "addDBTable".
     * 
     * @param data
     */
    private void addDBTable(Object data) {
        String tName = ((DBTable) data).getName();
        EList dbChildren = database.getDbChildren();
        for (Object object2 : dbChildren) {
            if (object2 instanceof DBTable) {
                boolean equals = ((DBTable) object2).getName().equals(tName);
                if (equals) {
                    return;
                }
            }
        }
        tables.add((DBTable) data);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.dnd.DropTargetListener#dragEnter(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public void dragEnter(DropTargetEvent event) {
        // always indicate a copy
        // event.detail = DND.DROP_COPY;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.dnd.DropTargetListener#dragLeave(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public void dragLeave(DropTargetEvent event) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.dnd.DropTargetListener#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public void dragOperationChanged(DropTargetEvent event) {
        // always indicate a copy
        // event.detail = DND.DROP_COPY;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.dnd.DropTargetListener#dragOver(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public void dragOver(DropTargetEvent event) {
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.dnd.DropTargetListener#drop(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public void drop(DropTargetEvent event) {
        int x = event.x;
        Point point = new Point(x, event.y);
        Point toControl = editor.getGraphicalControl().toControl(point);
        org.eclipse.draw2d.geometry.Point point2 = new org.eclipse.draw2d.geometry.Point(toControl.x, toControl.y);
        if (process != null) {
            TreeSelection selection = (TreeSelection) event.data;
            IWarehouseNode firstElement = (IWarehouseNode) selection.getFirstElement();
            String name = EGlobalComponentNames.getName(firstElement.getCategoryName(), event.detail);
            if (ENodeCategoryName.BLOCKS.equals(firstElement.getCategoryName())) {
                ProcessType type = (ProcessType) firstElement.getObject().getData();
                String uuid = type.getUuid();
                CompBlock compBlock = new CompBlock(uuid, type.getName());
                compBlock.setSize(AbstractGenericGEFEditor.getDefaultSize());
                compBlock.setColor(PreferenceConverter.getColor(DenguesUiPlugin.getDefault().getPreferenceStore(),
                        IDenguesPrefsConstant.DESIGNER_COLOR_BLOCK));
                compBlock.setLocation(point2);
                compBlock.setCompProcess(process);
                process.addCompBlock(compBlock);
                return;
            }
            if (name == null) {
                return;
            }
            IXMLComponent component = DenguesCorePlugin.getDefault().getDesignerCoreService().getComponentsFactory()
                    .getComponent(name);
            CompNode node = new CompNode(component);
            node.setSize(AbstractGenericGEFEditor.getDefaultSize());
            if (process.isGridEnabled()) {
                int tempVar = point2.x / AbstractGenericGEFEditor.getGrid();
                point2.x = tempVar * AbstractGenericGEFEditor.getGrid();
                tempVar = point2.y / AbstractGenericGEFEditor.getGrid();
                point2.y = tempVar * AbstractGenericGEFEditor.getGrid();
            }
            node.setLocation(point2);
            node.setCompProcess(process);
            node.setUniqueName(this.node.getLabel());

            process.addCompNode(node);
            process.addCompNodeLabel(node.getNodeLabel());
            process.addCompNodeStatus(node.getNodeStatus());

            DatabaseDiagram data = (DatabaseDiagram) firstElement.getObject().getData();
            Set keySet = data.getProperties().keySet();
            for (Object object : keySet) {
                String string = (String) object;
                node.setNodeParameterValue(string, data.getProperties().get(string));
            }

            List<MetadataTable> mtlist = new ArrayList<MetadataTable>();
            String metadataString = null;
            EList<DiagramChild> dbChildren = data.getDbChildren();
            for (DiagramChild dc : dbChildren) {
                if (dc instanceof DBTable) {
                    DBTable dc2 = (DBTable) dc;
                    mtlist.add(MetadataHelper.convertMetadataTable(dc2));
                    metadataString = WarehouseLabelUtil.getWarehouseNode(firstElement.getParent().getWarehousePath(), data
                            .getName(), dc2.getName());
                    break;
                }
            }
            node.setMetadataList(mtlist);
            if (metadataString != null) {
                node.setNodeParameterValue(ENodeParameterName.METADATA.getName(), metadataString);
            }
        } else if (database != null) {
            if (tables != null) {
                for (DBTable otable : tables) {
                    DBTable table = MetadataHelper.cloneDBTable(otable);
                    DBTableCreateCommand command = new DBTableCreateCommand(database, new Rectangle(point2, new Dimension(table
                            .getWidth(), table.getHeight())), table, false);
                    databaseEditor.getCommandStack().execute(command);
                    x += 185;
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.swt.dnd.DropTargetListener#dropAccept(org.eclipse.swt.dnd.DropTargetEvent)
     */
    public void dropAccept(DropTargetEvent event) {
    }

}
